/***********************************************************************
  [version]		1.00
  [author]		huangbin
  [date]		2022.08.19
  [email]		huangbinrd@163.com
 ----------------------------------------------------------------------
	COPYRIGHT 2015 SHENZHEN HB TECHNOLOGY DEVELOPMENT CO.,LTD. 
************************************************************************/
#include "inc.h"

#define RGB_IO_HIGH()	GPIOC->BSRR = GPIO_Pin_7
#define RGB_IO_LOW()	GPIOC->BRR = GPIO_Pin_7
void rgbWritColor(uint8_t r,uint8_t g,uint8_t b);

void Ws2812Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;		 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	RGB_IO_LOW();
	rgbWritColor(255,0,0);
}

/*
ws2812时序：
code 0： T0H= 220-380ns,T0L=580-1000ns
 ______
|      |_________|
code 1： T1H= 580-1000ns,T1L=580-1000ns
 __________
|          |_____|
reset code: > 280us
|________________|
RGB时序：GRB，high bit data at first
G7G6G5G4G3G2G1G0R7R6R5R4R3R2R1R0B7B6B5B4B3B2B1B0
先发送数据，最后发送一次reset（相当于更新信息，灯开始亮，并且后面的数据从头开始）
所以：在发送数据之前，DI线先拉低，每一个24bit颜色数据之间小于280us的低就不会认为是复位，而是下一个数据的准备时间。
发送数据的过程中，不能被中断打断，否则时序就乱了。
两种驱动方式：SPI，IO都可以
*/
//写一个RGB数据，在外面关中断.这个函数具有最底层移植性，其他灯的格式不一样的话，就要重新实现这个函数
//延时多少个ns,72Mhz=13.88ns
void Delayns(uint32_t ns)
{
	volatile uint32_t i;
	for(i = 0;i < ns/100;i++)
	{
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
	}
}
#define SendCode1()	do{					\
						RGB_IO_HIGH();	\
						Delayns(800);	\
						RGB_IO_LOW();	\
						Delayns(800);	\
						RGB_IO_HIGH();	\
					}while(0)
#define SendCode0()	do{					\
						RGB_IO_HIGH();	\
						Delayns(300);	\
						RGB_IO_LOW();	\
						Delayns(800);	\
						RGB_IO_HIGH();	\
					}while(0)
static void Ws2812WriteColor(uint8_t r,uint8_t g,uint8_t b)
{
   volatile uint32_t i;
   volatile uint8_t color;
	
	color = g;
	RGB_IO_LOW();
    for (i = 0; i < 8; i++)
    {
		if(color & 0x80)
		{
			SendCode1();
		}
		else
		{
			SendCode0();
		}
		color <<= 1;
	}
 	color = r;
    for (i = 0; i < 8; i++)
    {
		if(color & 0x80)
		{
			SendCode1();
		}
		else
		{
			SendCode0();
		}
		color <<= 1;
	}
 	color = b;
    for (i = 0; i < 8; i++)
    {
		if(color & 0x80)
		{
			SendCode1();
		}
		else
		{
			SendCode0();
		}
		color <<= 1;
	}	
	RGB_IO_HIGH();
}
void rgbReset(void)
{
	RGB_IO_HIGH();
	Delayns(1000*500);
	RGB_IO_LOW();
}
void rgbWritColor(uint8_t r,uint8_t g,uint8_t b)
{
	DISABLE_INTERRUPT();
	Ws2812WriteColor(r,g,b);
	rgbReset();
	ENABLE_INTERRUPT();
}






























//////////////////////////////////////////////////////////



